#ifndef SDK_INTERCOM_OBSERVER_H_
#define SDK_INTERCOM_OBSERVER_H_

#import <Foundation/Foundation.h>
#import "intercom_constants.h"
#import "weak_array.h"

@class NetClient;
@class ButtonMessage;
@class IntercomMessage;
@class SmartHomeMessage;
@class SecurityDevice;
@class SecurityMessage;
@class Intercom;

//App事件
@protocol IntercomAppDelegate<NSObject>

/* App 初始化callback, 理论上要在这个事件之后再创建别的，
 * 但是如果能确保初始化一定可以成功，就无需等待直接进行下一步
 */
- (void)onIntercomAppInitialized:(BOOL)result;

//SDK工作线程有某个线程挂了，此刻需要重启APP才行，一般来说不会发生，可以不管
- (void)onIntercomAppHangup:(int)thread_id thread_name:(NSString *)thread_name;

//音频设备被底层使用的情况
- (void)onAudioDeviceStateChanged:(int)state;

//视频采集设备被底层使用的情况
- (void)onCaptureDeviceStateChanged:(int)state;

//视频采集设备出现错误，可能是错误的参数导致的
- (void)onCaptureDeviceError:(int)err
                   from_here:(NSString *)from_here
                      reason:(NSString *)reason;

//摄像头预览的时候，如果设备渲染，则输出的分辨率跟着改变，上层可以根据这个通知重新设置新的Layer
- (void)onCaptureDimensionChanged:(int)width height:(int)height;

- (void)onRequestExternalVideoFrameEncode:(int)state width:(int)width height:(int)height;

//设备激活返回
- (void)onIntercomAppActivated:(int)err
                          type:(NSString *)type
                       message:(NSString *)message;

//添加某个家庭的异步返回
- (void)onIntercomFamilyInitialized:(NSString *)fid result:(BOOL)result;

@end

//代理事件回调
@protocol IntercomProxyDelegate<NSObject>

/**
 * 代理上线或者下线通知
 * 在收到这个事件之后，需要通过proxy_id查询代理的在线状态
 * 代理的在线状态有两种,LAN/WAN，同一个代理同时在LAN和WAN在线
 */
- (void)onIntercomProxyStateChanged:(Intercom *)intercom
                           proxy_id:(NSString *)proxy_id
                             online:(BOOL)online;

/**
 * 代理的中间状态发生变化，就是说，代理是有效的，但是LAN／WAN的其中某个
 * 状态发生变化，如果UI层需要分别显示LAN／WAN在线状态，通过这个方法来更新
 */
- (void)onIntercomProxyOnlineStateChanged:(Intercom *)intercom
                                 proxy_id:(NSString *)proxy_id
                                   router:(Router)router
                                   online:(BOOL)online;

/**
 * 终端上线下线通知
 * 终端下线表示这个终端彻底从LAN或者WAN上断开，UI层需要去掉相关的信息
 */
- (void)onIntercomClientStateChanged:(Intercom *)intercom
                           client_id:(NSString *)client_id
                              online:(BOOL)online;

/**
 * 终端的中间状态发生改变，比如从某个代理中掉线，或者WAN上掉线
 * 但终端是可用的，继续保持显示状态
 * proxy_id:可以知道在哪个代理上发生变化，只有router：LAN的时候才有效
 */
- (void)onIntercomClientOnlineStateChanged:(Intercom *)intercom
                                 client_id:(NSString *)client_id
                                  proxy_id:(NSString *)proxy_id
                                    router:(Router)router
                                    online:(BOOL)online;

- (void)onIntercomInternetStateChanged:(Intercom *)intercom online:(BOOL)online;

- (void)onIntercomProxyDeviceChanged:(Intercom *)intercom
                            proxy_id:(NSString *)proxy_id
                              router:(Router)router
                           device_id:(NSString *)device_id;

//通过代理收到按键消息，IOS可以不管
- (void)onIntercomButtonMessageArrival:(Intercom *)intercom
                                router:(Router)router
                            net_client:(NetClient *)net_client
                               message:(ButtonMessage *)message;

/**
 * 我们可以通过Proxy给家庭其他设备发送消息，这里会收到其他设备发送的消息
 * 消息用IntercomMessage打包，正文在 content中
 */
- (void)onIntercomProxyFamilyMessageArrival:(Intercom *)intercom
                                     router:(Router)router
                                 net_client:(NetClient *)net_client
                                    message:(IntercomMessage *)message;

//消息发送失败，对方不在线，或者其他原因，所有通过代理发送的消息都可能失败
//不可能是门禁消息和智能家居消息，因为这二者在底层已经处理了
- (void)onIntercomProxyMessageSendFailed:(Intercom *)intercom
                                  router:(Router)router
                              net_client:(NetClient *)net_client
                                 message:(NSString *)message;

//这里可能会有管理平台发来的消息，直接解析字典即可
- (void)onIntercomExtendedMessageArrival:(Intercom *)intercom
                                 message:(NSDictionary *)message;

@end

//门禁事件的回调
@protocol IntercomConversationDelegate<NSObject>

/** 某个会话已经收到视频数据，此刻，我们可以通知底层生成快照 */
- (void)onIntercomVideoReady:(Intercom *)intercom
                  session_id:(NSString *)session_id;

- (void)onIntercomVideoDimensionChanged:(Intercom *)intercom
                             session_id:(NSString *)session_id
                                  width:(int)width
                                 height:(int)height;

/**
 * 生成了一张视频快照，并保存到filename指定的文件中
 * 一般而言，我们需要生成三个快照，时间间隔一定的周期，比如1s
 */
- (void)onIntercomSnapshotReady:(Intercom *)intercom
                     session_id:(NSString *)session_id
                       filename:(NSString *)filename;

//从RTP协议收到DTMF，IOS可以不管
- (void)onIntercomStreamDTMFArrival:(Intercom *)intercom
                         session_id:(NSString *)session_id
                           protocol:(int)protocol
                               dtmf:(int)dtmf;

/** 媒体流状态发生变化 */
- (void)onIntercomStreamStateChanged:(Intercom *)intercom
                          session_id:(NSString *)session_id
                          media_type:(TransportMediaType)media_type
                               state:(StreamState)state;

/** 媒体传输开始了*/
- (void)onIntercomTransportStart:(Intercom *)intercom
                      session_id:(NSString *)session_id
                      media_type:(TransportMediaType)media_type;

/** 传输定期的统计数据，比如收发了多少字节数据
 * 统计的时间周期就是MediaConfig中配置的单位*/
- (void)onIntercomTransportStatistics:(Intercom *)intercom
                           session_id:(NSString *)session_id
                           media_type:(TransportMediaType)media_type
                           recv_bytes:(long long)recv_bytes
                           send_bytes:(long long)send_bytes;

/**
 *ICE协商结果，result=0表示成功，其他表示失败
 *ICE协商成功，表示媒体传输将通过P2P的方式传输，不会占用服务器资源
 *每个会话可能包含语音和视频，分别通过各自的通道进行传输
 */
- (void)onIntercomTransportIceNegotiationResult:(Intercom *)intercom
                                     session_id:(NSString *)session_id
                                     media_type:(TransportMediaType)media_type
                                         result:(NSInteger)result;

/** sip登陆状态发生变化 */
- (void)onIntercomSipStateChanged:(Intercom *)intercom
                            identity:(NSString *)identity //sip account
                            state:(SipRegistrationState)state;

/** 收到门禁的消息，我们根据消息来决定如何处理呼叫 */
- (void)onIntercomMessageArrival:(Intercom *)intercom
                          router:(Router)router
                      net_client:(NetClient *)net_client
                         message:(IntercomMessage *)message;

- (void)onSipDTMFReady:(Intercom *)intercom
            session_id:(NSString *)session_id
                  dtmf:(int)dtmf;

@end

@protocol IntercomSmartHomeDelegate<NSObject>

- (void)onSmartHomeSecurityDeviceStateChanged:(Intercom *)intercom
                                       device:(SecurityDevice *)device
                                       online:(BOOL)online;

- (void)onSmartHomeSecurityDeviceOnlineStateChanged:(Intercom *)intercom
                                             device:(SecurityDevice *)device
                                             router:(int)router
                                             online:(BOOL)online;

- (void)onSmartHomeMessage:(Intercom *)intercom
                    device:(SecurityDevice *)device
                   message:(SmartHomeMessage *)message;

- (void)onSmartHomeAlarm:(Intercom *)intercom
                  device:(SecurityDevice *)device
       smarthome_message:(SmartHomeMessage *)smarthome_message
        security_message:(SecurityMessage *)security_message;

@end

@interface IntercomAppDelegateHolder : WeakReferenceArray

- (void)onIntercomAppInitialized:(BOOL)result;

- (void)onIntercomAppHangup:(int)thread_id thread_name:(NSString *)thread_name;

//state == 0 : started, 1: stopped
- (void)onAudioDeviceStateChanged:(int)state;

- (void)onCaptureDeviceStateChanged:(int)state;

- (void)onCaptureDeviceError:(int)err
                   from_here:(NSString *)from_here
                      reason:(NSString *)reason;

- (void)onCaptureDimensionChanged:(int)width height:(int)height;

- (void)onRequestExternalVideoFrameEncode:(int)state width:(int)width height:(int)height;

- (void)onIntercomAppActivated:(int)err
                          type:(NSString *)type
                       message:(NSString *)message;

- (void)onIntercomFamilyInitialized:(NSString *)fid result:(BOOL)result;

@end

@interface IntercomProxyDelegateHolder : WeakReferenceArray

/**
 * 代理上线或者下线通知
 * 在收到这个事件之后，需要通过proxy_id查询代理的在线状态
 * 代理的在线状态有两种,LAN/WAN，同一个代理同时在LAN和WAN在线
 */
- (void)onIntercomProxyStateChanged:(Intercom *)intercom
                           proxy_id:(NSString *)proxy_id
                             online:(BOOL)online;

/**
 * 代理的中间状态发生变化，就是说，代理是有效的，但是LAN／WAN的其中某个
 * 状态发生变化，如果UI层需要分别显示LAN／WAN在线状态，通过这个方法来更新
 */
- (void)onIntercomProxyOnlineStateChanged:(Intercom *)intercom
                                 proxy_id:(NSString *)proxy_id
                                   router:(Router)router
                                   online:(BOOL)online;

/**
 * 终端上线下线通知
 * 终端下线表示这个终端彻底从LAN或者WAN上断开，UI层需要去掉相关的信息
 */
- (void)onIntercomClientStateChanged:(Intercom *)intercom
                           client_id:(NSString *)client_id
                              online:(BOOL)online;

/**
 * 终端的中间状态发生改变，比如从某个代理中掉线，或者WAN上掉线
 * 但终端是可用的，继续保持显示状态
 * proxy_id:可以知道在哪个代理上发生变化，只有router：LAN的时候才有效
 */
- (void)onIntercomClientOnlineStateChanged:(Intercom *)intercom
                                 client_id:(NSString *)client_id
                                  proxy_id:(NSString *)proxy_id
                                    router:(Router)router
                                    online:(BOOL)online;

- (void)onIntercomInternetStateChanged:(Intercom *)intercom online:(BOOL)online;

- (void)onIntercomProxyDeviceChanged:(Intercom *)intercom
                            proxy_id:(NSString *)proxy_id
                              router:(Router)router
                           device_id:(NSString *)device_id;
/**
 * 通过代理收到按键消息
 */
- (void)onIntercomButtonMessageArrival:(Intercom *)intercom
                                router:(Router)router
                            net_client:(NetClient *)net_client
                               message:(ButtonMessage *)message;

/**
 * family message from other device
 */
- (void)onIntercomProxyFamilyMessageArrival:(Intercom *)intercom
                                     router:(Router)router
                                 net_client:(NetClient *)net_client
                                    message:(IntercomMessage *)message;

- (void)onIntercomProxyMessageSendFailed:(Intercom *)intercom
                                  router:(Router)router
                              net_client:(NetClient *)net_client
                                 message:(NSString *)message;

//maybe from Management Platform
- (void)onIntercomExtendedMessageArrival:(Intercom *)intercom
                                 message:(NSDictionary *)message;
@end

@interface IntercomConversationDelegateHolder : WeakReferenceArray

/** 某个会话已经收到视频数据，此刻，我们可以通知底层生成快照 */
- (void)onIntercomVideoReady:(Intercom *)intercom
                  session_id:(NSString *)session_id;

- (void)onIntercomVideoDimensionChanged:(Intercom *)intercom
                             session_id:(NSString *)session_id
                                  width:(int)width
                                 height:(int)height;

/**
 * 生成了一张视频快照，并保存到filename指定的文件中
 * 一般而言，我们需要生成三个快照，时间间隔一定的周期，比如1s
 */
- (void)onIntercomSnapshotReady:(Intercom *)intercom
                     session_id:(NSString *)session_id
                       filename:(NSString *)filename;

- (void)onIntercomStreamDTMFArrival:(Intercom *)intercom
                         session_id:(NSString *)session_id
                           protocol:(int)protocol
                               dtmf:(int)dtmf;

/** 媒体流状态发生变化 */
- (void)onIntercomStreamStateChanged:(Intercom *)intercom
                          session_id:(NSString *)session_id
                          media_type:(TransportMediaType)media_type
                               state:(StreamState)state;

/** 媒体传输开始了*/
- (void)onIntercomTransportStart:(Intercom *)intercom
                      session_id:(NSString *)session_id
                      media_type:(TransportMediaType)media_type;

/** 传输定期的统计数据，比如收发了多少字节数据
 * interval：统计的时间周期，秒单位，比如30s*/
- (void)onIntercomTransportStatistics:(Intercom *)intercom
                           session_id:(NSString *)session_id
                           media_type:(TransportMediaType)media_type
                           recv_bytes:(long long)recv_bytes
                           send_bytes:(long long)send_bytes;

/**
 *ICE协商结果，result=0表示成功，其他表示失败
 *ICE协商成功，表示媒体传输将通过P2P的方式传输，不会占用服务器资源
 *每个会话可能包含语音和视频，分别通过各自的通道进行传输
 */
- (void)onIntercomTransportIceNegotiationResult:(Intercom *)intercom
                                     session_id:(NSString *)session_id
                                     media_type:(TransportMediaType)media_type
                                         result:(NSInteger)result;

/** sip登陆状态发生变化 */
- (void)onIntercomSipStateChanged:(Intercom *)intercom
                            identity:(NSString *)identity
                            state:(SipRegistrationState)state;

/** 收到门禁的消息，我们根据消息来决定如何处理呼叫 */
- (void)onIntercomMessageArrival:(Intercom *)intercom
                          router:(Router)router
                      net_client:(NetClient *)net_client
                         message:(IntercomMessage *)message;

- (void)onSipDTMFReady:(Intercom *)intercom
            session_id:(NSString *)session_id
                  dtmf:(int)dtmf;
@end

@interface IntercomSmartHomeDelegateHolder : WeakReferenceArray

- (void)onSmartHomeSecurityDeviceStateChanged:(Intercom*)intercom
                                       device:(SecurityDevice*) device
                                       online:(BOOL)online;

- (void)onSmartHomeSecurityDeviceOnlineStateChanged:(Intercom*)intercom
                                             device:(SecurityDevice*) device
                                             router:(int)router
                                             online:(BOOL)online;

- (void)onSmartHomeMessage:(Intercom*)intercom
                    device:(SecurityDevice*)device
                   message:(SmartHomeMessage*)message;

- (void)onSmartHomeAlarm:(Intercom*)intercom
                  device:(SecurityDevice*)device
       smarthome_message:(SmartHomeMessage*)smarthome_message
        security_message:(SecurityMessage*)security_message;
@end

#endif //SDK_INTERCOM_OBSERVER_H_
